package model

import (
	"context"
	"database/sql"
	"fmt"
	"go-zero-mall/app/admin/cmd/rpc/pd"
	"strings"

	"github.com/Masterminds/squirrel"
	"github.com/jinzhu/copier"
	"github.com/zeromicro/go-zero/core/stores/cache"
	"github.com/zeromicro/go-zero/core/stores/sqlx"
	"github.com/zeromicro/go-zero/core/stringx"
)

var _ UmsAdminModel = (*customUmsAdminModel)(nil)

type (
	// UmsAdminModel is an interface to be customized, add more methods here,
	// and implement the added methods in customUmsAdminModel.
	UmsAdminModel interface {
		umsAdminModel
		FindByPageParam(ctx context.Context, rowBuilder squirrel.SelectBuilder, pageNum, pageSize int64) ([]*UmsAdmin, error)
		FindOneById(context context.Context, id int64) (*UmsAdmin, error)
		FindOneByName(ctx context.Context, username string) (*UmsAdmin, error)
		FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder) (int64, error)
		InsertSession(ctx context.Context, session sqlx.Session, data *UmsAdmin) (sql.Result, error)
		Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error
		RowBuilder() squirrel.SelectBuilder
		CountBuilder(field string) squirrel.SelectBuilder
		//查询用户菜单
		FindMenus(ctx context.Context, userId int64) ([]*pd.Menu, error)
		//查询用户角色
		FindRoles(ctx context.Context, userId int64) ([]*pd.Role, error)
		//查询用户信息
		FindInfo(ctx context.Context, userId int64) (*pd.AdminInfoResp, error)
		//更新用户信息排除登录时间
		UpdateNoLoginTime(ctx context.Context, data *UmsAdmin) error
	}

	customUmsAdminModel struct {
		*defaultUmsAdminModel
	}
)

// NewUmsAdminModel returns a model for the database table.
func NewUmsAdminModel(conn sqlx.SqlConn, c cache.CacheConf) UmsAdminModel {
	return &customUmsAdminModel{
		defaultUmsAdminModel: newUmsAdminModel(conn, c),
	}
}
func (m *defaultUmsAdminModel) InsertSession(ctx context.Context, session sqlx.Session, data *UmsAdmin) (sql.Result, error) {
	umsAdminIdKey := fmt.Sprintf("%s%v", cacheUmsAdminIdPrefix, data.Id)
	ret, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
		query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?, ?, ?, ?)", m.table, umsAdminRowsExpectAutoSet)
		if session != nil {
			return session.ExecCtx(ctx, query, data.Username, data.Password, data.Icon, data.Email, data.NickName, data.Note, data.LoginTime, data.Status)
		}
		return conn.ExecCtx(ctx, query, data.Username, data.Password, data.Icon, data.Email, data.NickName, data.Note, data.LoginTime, data.Status)
	}, umsAdminIdKey)
	return ret, err
}
func (m *defaultUmsAdminModel) UpdateNoLoginTime(ctx context.Context, data *UmsAdmin) error {
	umsAdminIdKey := fmt.Sprintf("%s%v", cacheUmsAdminIdPrefix, data.Id)
	umsAdminRowsNoLoginTimeWithPlaceHolder := strings.Join(stringx.Remove(umsAdminFieldNames, "`id`", "`create_time`", "`update_time`", "`login_time`"), "=?,") + "=?"
	_, err := m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
		query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, umsAdminRowsNoLoginTimeWithPlaceHolder)
		return conn.ExecCtx(ctx, query, data.Username, data.Password, data.Icon, data.Email, data.NickName, data.Note, data.Status, data.Id)
	}, umsAdminIdKey)
	return err
}

//查询用户菜单
func (m *defaultUmsAdminModel) FindMenus(ctx context.Context, userId int64) ([]*pd.Menu, error) {
	query, values, err := squirrel.Select("m.*").From("ums_menu m").LeftJoin("ums_role_menu_relation rm on m.id=rm.role_id").LeftJoin("ums_admin_role_relation ar on FIND_IN_SET(rm.role_id,ar.role_ids)").Where("ar.id=?", userId).ToSql()
	if err != nil {
		return nil, err
	}
	var menu []*UmsMenu
	err = m.QueryRowsNoCacheCtx(ctx, &menu, query, values...)

	var d []*pd.Menu
	copier.Copy(&d, menu)
	switch err {
	case nil:
		return d, nil
	default:
		return nil, err
	}
}

// 根据用户查询角色
func (m *defaultUmsAdminModel) FindRoles(ctx context.Context, userId int64) ([]*pd.Role, error) {
	query, values, err := squirrel.Select("ur.*").From("ums_role ur").LeftJoin("ums_admin_role_relation ar on FIND_IN_SET(ur.id,ar.role_ids)").Where("ar.id=?", userId).ToSql()
	if err != nil {
		return nil, err
	}
	var roles []*UmsRole
	err = m.QueryRowsNoCacheCtx(ctx, &roles, query, values...)
	var d []*pd.Role
	copier.Copy(&d, roles)
	switch err {
	case nil:
		return d, nil
	default:
		return nil, err
	}
}
func (m *defaultUmsAdminModel) FindInfo(ctx context.Context, userId int64) (*pd.AdminInfoResp, error) {
	query, values, err := squirrel.Select("id,username,icon,email,nick_name,note,status").From(m.table).ToSql()
	if err != nil {
		return nil, err
	}
	var info *UmsAdmin
	err = m.QueryRowNoCacheCtx(ctx, info, query, values...)
	var d *pd.AdminInfoResp
	copier.Copy(&d, info)
	switch err {
	case nil:
		return d, nil
	default:
		return nil, err
	}
}
func (m *defaultUmsAdminModel) FindByPageParam(ctx context.Context, rowBuilder squirrel.SelectBuilder, pageNum, pageSize int64) ([]*UmsAdmin, error) {

	if pageSize < 1 {
		pageSize = 1
	}
	if pageNum < 1 {
		pageNum = 1
	}
	offset := (pageNum - 1) * pageSize
	query, values, err := rowBuilder.Limit(uint64(pageSize)).Offset(uint64(offset)).ToSql()
	if err != nil {
		return nil, err
	}
	var resp []*UmsAdmin
	err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
	switch err {
	case nil:
		return resp, nil
	default:
		return nil, err
	}
}
func (m *defaultUmsAdminModel) FindOneById(context context.Context, id int64) (*UmsAdmin, error) {
	var resp UmsAdmin
	query, values, _ := m.RowBuilder().Where("id=?", id).Limit(1).ToSql()
	err := m.QueryRowNoCacheCtx(context, &resp, query, values...)
	switch err {
	case nil:
		return &resp, nil
	default:
		return nil, err
	}
}
func (m *defaultUmsAdminModel) FindOneByName(ctx context.Context, username string) (*UmsAdmin, error) {
	var resp UmsAdmin
	query, values, _ := m.RowBuilder().Where("username=?", username).Limit(1).ToSql()
	err := m.QueryRowNoCacheCtx(ctx, &resp, query, values...)
	switch err {
	case nil:
		return &resp, nil
	default:
		return nil, err
	}
}
func (m *defaultUmsAdminModel) FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder) (int64, error) {
	query, values, err := countBuilder.ToSql()
	if err != nil {
		return 0, err
	}
	var resp int64
	err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...)
	switch err {
	case nil:
		return resp, nil
	default:
		return 0, err
	}
}

// export logic
func (m *defaultUmsAdminModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error {
	return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error {
		return fn(ctx, session)
	})

}

// export logic
func (m *defaultUmsAdminModel) RowBuilder() squirrel.SelectBuilder {
	return squirrel.Select(umsAdminRows).From(m.table)
}

// export logic
func (m *defaultUmsAdminModel) CountBuilder(field string) squirrel.SelectBuilder {
	return squirrel.Select("COUNT(" + field + ")").From(m.table)
}

// export logic
func (m *defaultUmsAdminModel) SumBuilder(field string) squirrel.SelectBuilder {
	return squirrel.Select("IFNULL(SUM(" + field + "),0)").From(m.table)
}
